/**	@file 	Number.h
 *	@brief The representation of numbers (Integer, Rational, real).
 *	This file use an external libray for arithmetics. The required library is GNU MP. 
 *	More information about obtaining and instalation you can see at http://gmplib.org/ . */
#ifndef Number_majdo_
#define Number_majdo_
#include "Ex.h"
#include <gmpxx.h>
namespace sympycpp {
//	@brief alias for int that is intial type of mpq_class from GMP library
typedef  int N_Rational_init;
//	@brief alias for double that is intial type of mpf_class from GMP library
typedef  double N_Real_init;
//	@brief alias for mpq_class that is used for storing rational numbers in class Number
typedef mpq_class N_Rational;
//	@brief alias for mpf_class that is used for storing real numbers in class Number
typedef mpf_class N_Real;
/**	@class Number
 *	@brief	The class Number covers integers, rational and real numbers (all in one).
 *	The class Number encapsulates numbers and operations with them. */
class Number : public Ex {
	///	@brief this is a place for storing of rational numbers or integers 
	N_Rational ratioVal_;
	///	@brief this is a place for storing of real numbers 
	N_Real realVal_;
	///	@brief Information about the type of the stored number (true == rational, false == real).
	bool isRatio_;
	///	@brief Count of printed digits from the real number.
	static int precision;
	/** 	@brief The control and conversion of the actual mode and the domain of the stored number.
	 * 	The inner representation of the real number is converted to the integer representation
	 * 	if the real number doesn't contain a decimal fraction. */
	void checkVal();
	/**	@brief The conversion of numbers into the GMP library type. (real numbers) 
	 * 	@warning This function returns real number. If represented number is rational number
	 * 	or integer then the returned value is not guaranteed. */
	inline N_Real getN_Real() const;
	/**	@brief The conversion of numbers into the GMP library type. (real numbers) 
	 * 	@warning This function returns rational number. If represented number is real number
	 * 	then the returned value is not guaranteed. */
	inline N_Rational getN_Rational() const;
public:
	/**	@brief Set the number of printed digits. */
	static void setPrecision(const int i) { 
		precision = i;
	}
	/**	@brief Return the number of printed digits. */
	static int getPrecision() {
		return precision;
	}
	///	@brief Construction from the external real type.
	Number(const N_Real &);
	///	@brief Construction from the external rational type.
	Number(const N_Rational &);
	///	@brief Construction from int.
	Number(const N_Real_init);
	///	@brief Construction from double.
	Number(const N_Rational_init);
	/**	@brief Construction of real number from string.
	 *	Type of first parameter marks construction of real number. It makes
	 *	this constriuctor distinguishable from textual constructor of rational number.*/
	Number(const double, const char *);
	/**	@brief Construction of rational number from string.
	 *	Type of first parameter marks construction of rational number. It makes 
	 *	this constriuctor distinguishable from textual constructor of real number.*/
	Number(const int, const char *);
	virtual void sign(const Sign s);
	Sign sign() const {
		return sign_;
	}
	virtual std::string treeView(const int i ) const;
	virtual bool isInteger() const;
	virtual bool isRational() const {
		return isRatio_;
	}
	virtual bool isReal() const {
		return !isRatio_;
	}
	virtual Ex * diff(const Sym & s) const;
	virtual Ex * copy() const {
		return new Number(*this);
	}
	virtual std::string str() const;
	virtual std::string unsigned_str() const;
	///	@brief  The transformation of the number into the std::string (usage of paranthesis is inhibited).
	virtual std::string str2() const;
	///	@brief Is the number convertible into int (is integer and less than MAX_INT)?
	bool isInt() const;
	/**	@brief The conversion into int.
	 * 	@throws The exception NotInt will be thrown if the converted number is not an integer or is too big. */ 
	int getInt() const;
	///	@brief The value of the number is set to the factorial of the input number.
	void setToFactorial(const int x); 
	///	@brief The value of the number is set to the addition of the input numbers.
	void setToAddition(const Number &, const Number &);
	///	@brief The value of the number is set to the subtraction of the input numbers.
	void setToSubtraction(const Number &, const Number &);
	///	@brief The value of the number is set to the multiplication of the input numbers.
	void setToMultiplication(const Number &, const Number &);
	/**	@brief The value of the number is set to the division of the input numbers.
	 * 	@param n is a numerator
	 * 	@param d is a denominator
	 * 	@throws Exception ZeroDivision will be thrown if the divisor is zero. */
	void setToDivision(const Number & n, const Number & d);
	/** 	@brief The value of the number is adjusted to power, that base 
	 * 	is the stored number and exponent is theinput integer. */
	void setToPower(const int);
	///	@brief Are the stored number and the input number equal?
	bool eq(const N_Real &) const;
	///	@brief Are the stored number and the input number equal?
	bool eq(const N_Rational &) const;
	///	@brief Are the stored number and the input number equal?
	bool eq(const N_Real_init) const;
	///	@brief Are the stored number and the input number equal?
	bool eq(const N_Rational_init) const;
	///	@brief Are the stored number and the input number equal?
	bool eq(const Number &) const;
	///	@brief Is the strored number lower than the input number?
	bool lt(const Number &) const;
	///	@brief Is the strored number lower than the input number?
	bool lt(const N_Real &) const;
	///	@brief Is the strored number lower than the input number?
	bool lt(const N_Rational &) const;
	///	@brief Is the strored number lower than the input number?
	bool lt(const N_Real_init) const;
	///	@brief Is the strored number lower than the input number?
	bool lt(const N_Rational_init) const;
	///	@brief Adjusting the new valule of the number. 
	void setValue(const Number &);
	///	@brief Adjusting of the new valule of the number. 
	void setValue(const N_Rational_init);
	///	@brief Adjusting of the new valule of the number. 
	void setValue(const N_Real_init);
	///	@brief Adjusting of the new valule of the number. 
	void setValue(const N_Rational &);
	///	@brief Adjusting of the new valule of the number. 
	void setValue(const N_Real &);
	///	@brief The absolute value of the number.
	Number abs() const;	
};
}
#endif
